package com.heima.ThreadPool.Semaphore;

import java.util.concurrent.Semaphore;
import java.util.concurrent.ThreadPoolExecutor;

/**
 * @Author: Ethan Yankang
 * @Program: 面试必会代码
 * @Date: 2024-08-30 16:39
 **/
/*
* 定义
 JUC下的一个工具类，可以通过其限制执行的线程数量，达到限流的效果

* 作用
 控制某个方法允许并发访问线程的数量

* 原理
 当一个线程执行时先通过其方法进行获取许可操作，获取到许可的线程继续执行业务逻辑，当线程执行完成后进行释放许可操作，未获取到许可的线程进行等待或者直接结束。

* 方法
 semaphore.acquire()
  请求一个信号量，这时候的信号量个数-1（一旦没有可使用的信号量，也即信号量个数变为负数时，再次请求的时候就会阻塞，直到其他线程释放了信号量）
 semaphore.release()
  释放一个信号量，此时信号量个数+1
  *
  *
  * 核心
  * 在acquire()与release()之间的代码块是受到保护的。只有当前线程持有 的信号量释放了其他线程才能继续访问该保护区域
*/


public class SemaphoreTest {
    public static void main(String[] args) {
//        char c='a';
//        1.创建Semaphore对象
        Semaphore semaphore = new Semaphore(1);
//        2.创建10个线程同时运行
        for (int i = 0; i < 10; i++) {
            final int id=i;
            new Thread(()->{
                try {
                    System.out.println(Thread.currentThread().getName()+"获得了许可");
//                    System.out.println((char) (c+id));
                    semaphore.acquire();
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
                try {
                    System.out.println(Thread.currentThread().getName()+"is running" +
                            "(这是存放在acquire()与release()方法之间的，所以会被保护，只能获取信号量才能进入其中)");
                    try {
                        Thread.sleep(100);
                    }catch (InterruptedException e){
                        e.printStackTrace();
                    }

                }finally {
                    System.out.println(Thread.currentThread().getName()+"释放了许可");
                    semaphore.release();
                }
            }).start();
        }
    }
}

/*
 * @description 可以利用将semaphore的信号量设置为1，从而实现线程按顺序打印的效果，之前是通过join()让指定的线程按顺序执行,现在多了一个！
 * @params
 * @return
 */
